{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Creating a Customer Service Agent with Client-Side Tools\n",
    "\n",
    "In this recipe, we'll demonstrate how to create a customer service chatbot using Claude 3 plus client-side tools. The chatbot will be able to look up customer information, retrieve order details, and cancel orders on behalf of the customer. We'll define the necessary tools and simulate synthetic responses to showcase the chatbot's capabilities."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1: Set up the environment\n",
    "\n",
    "First, let's install the required libraries and set up the Claude API client."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install anthropic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "import anthropic\n",
    "\n",
    "client = anthropic.Client()\n",
    "MODEL_NAME = \"claude-opus-4-1\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2: Define the client-side tools\n",
    "\n",
    "Next, we'll define the client-side tools that our chatbot will use to assist customers. We'll create three tools: get_customer_info, get_order_details, and cancel_order."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [\n",
    "    {\n",
    "        \"name\": \"get_customer_info\",\n",
    "        \"description\": \"Retrieves customer information based on their customer ID. Returns the customer's name, email, and phone number.\",\n",
    "        \"input_schema\": {\n",
    "            \"type\": \"object\",\n",
    "            \"properties\": {\n",
    "                \"customer_id\": {\n",
    "                    \"type\": \"string\",\n",
    "                    \"description\": \"The unique identifier for the customer.\",\n",
    "                }\n",
    "            },\n",
    "            \"required\": [\"customer_id\"],\n",
    "        },\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"get_order_details\",\n",
    "        \"description\": \"Retrieves the details of a specific order based on the order ID. Returns the order ID, product name, quantity, price, and order status.\",\n",
    "        \"input_schema\": {\n",
    "            \"type\": \"object\",\n",
    "            \"properties\": {\n",
    "                \"order_id\": {\n",
    "                    \"type\": \"string\",\n",
    "                    \"description\": \"The unique identifier for the order.\",\n",
    "                }\n",
    "            },\n",
    "            \"required\": [\"order_id\"],\n",
    "        },\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"cancel_order\",\n",
    "        \"description\": \"Cancels an order based on the provided order ID. Returns a confirmation message if the cancellation is successful.\",\n",
    "        \"input_schema\": {\n",
    "            \"type\": \"object\",\n",
    "            \"properties\": {\n",
    "                \"order_id\": {\n",
    "                    \"type\": \"string\",\n",
    "                    \"description\": \"The unique identifier for the order to be cancelled.\",\n",
    "                }\n",
    "            },\n",
    "            \"required\": [\"order_id\"],\n",
    "        },\n",
    "    },\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 3: Simulate synthetic tool responses\n",
    "\n",
    "Since we don't have real customer data or order information, we'll simulate synthetic responses for our tools. In a real-world scenario, these functions would interact with your actual customer database and order management system."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_customer_info(customer_id):\n",
    "    # Simulated customer data\n",
    "    customers = {\n",
    "        \"C1\": {\"name\": \"John Doe\", \"email\": \"john@example.com\", \"phone\": \"123-456-7890\"},\n",
    "        \"C2\": {\"name\": \"Jane Smith\", \"email\": \"jane@example.com\", \"phone\": \"987-654-3210\"},\n",
    "    }\n",
    "    return customers.get(customer_id, \"Customer not found\")\n",
    "\n",
    "\n",
    "def get_order_details(order_id):\n",
    "    # Simulated order data\n",
    "    orders = {\n",
    "        \"O1\": {\n",
    "            \"id\": \"O1\",\n",
    "            \"product\": \"Widget A\",\n",
    "            \"quantity\": 2,\n",
    "            \"price\": 19.99,\n",
    "            \"status\": \"Shipped\",\n",
    "        },\n",
    "        \"O2\": {\n",
    "            \"id\": \"O2\",\n",
    "            \"product\": \"Gadget B\",\n",
    "            \"quantity\": 1,\n",
    "            \"price\": 49.99,\n",
    "            \"status\": \"Processing\",\n",
    "        },\n",
    "    }\n",
    "    return orders.get(order_id, \"Order not found\")\n",
    "\n",
    "\n",
    "def cancel_order(order_id):\n",
    "    # Simulated order cancellation\n",
    "    if order_id in [\"O1\", \"O2\"]:\n",
    "        return True\n",
    "    else:\n",
    "        return False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 4: Process tool calls and return results\n",
    "\n",
    "We'll create a function to process the tool calls made by Claude and return the appropriate results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def process_tool_call(tool_name, tool_input):\n",
    "    if tool_name == \"get_customer_info\":\n",
    "        return get_customer_info(tool_input[\"customer_id\"])\n",
    "    elif tool_name == \"get_order_details\":\n",
    "        return get_order_details(tool_input[\"order_id\"])\n",
    "    elif tool_name == \"cancel_order\":\n",
    "        return cancel_order(tool_input[\"order_id\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 5: Interact with the chatbot\n",
    "\n",
    "Now, let's create a function to interact with the chatbot. We'll send a user message, process any tool calls made by Claude, and return the final response to the user."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "\n",
    "\n",
    "def chatbot_interaction(user_message):\n",
    "    print(f\"\\n{'=' * 50}\\nUser Message: {user_message}\\n{'=' * 50}\")\n",
    "\n",
    "    messages = [{\"role\": \"user\", \"content\": user_message}]\n",
    "\n",
    "    response = client.messages.create(\n",
    "        model=MODEL_NAME, max_tokens=4096, tools=tools, messages=messages\n",
    "    )\n",
    "\n",
    "    print(\"\\nInitial Response:\")\n",
    "    print(f\"Stop Reason: {response.stop_reason}\")\n",
    "    print(f\"Content: {response.content}\")\n",
    "\n",
    "    while response.stop_reason == \"tool_use\":\n",
    "        tool_use = next(block for block in response.content if block.type == \"tool_use\")\n",
    "        tool_name = tool_use.name\n",
    "        tool_input = tool_use.input\n",
    "\n",
    "        print(f\"\\nTool Used: {tool_name}\")\n",
    "        print(\"Tool Input:\")\n",
    "        print(json.dumps(tool_input, indent=2))\n",
    "\n",
    "        tool_result = process_tool_call(tool_name, tool_input)\n",
    "\n",
    "        print(\"\\nTool Result:\")\n",
    "        print(json.dumps(tool_result, indent=2))\n",
    "\n",
    "        messages = [\n",
    "            {\"role\": \"user\", \"content\": user_message},\n",
    "            {\"role\": \"assistant\", \"content\": response.content},\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": [\n",
    "                    {\n",
    "                        \"type\": \"tool_result\",\n",
    "                        \"tool_use_id\": tool_use.id,\n",
    "                        \"content\": str(tool_result),\n",
    "                    }\n",
    "                ],\n",
    "            },\n",
    "        ]\n",
    "\n",
    "        response = client.messages.create(\n",
    "            model=MODEL_NAME, max_tokens=4096, tools=tools, messages=messages\n",
    "        )\n",
    "\n",
    "        print(\"\\nResponse:\")\n",
    "        print(f\"Stop Reason: {response.stop_reason}\")\n",
    "        print(f\"Content: {response.content}\")\n",
    "\n",
    "    final_response = next(\n",
    "        (block.text for block in response.content if hasattr(block, \"text\")),\n",
    "        None,\n",
    "    )\n",
    "\n",
    "    print(f\"\\nFinal Response: {final_response}\")\n",
    "\n",
    "    return final_response"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 6: Test the chatbot\n",
    "Let's test our customer service chatbot with a few sample queries."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "==================================================\n",
      "User Message: Can you tell me the email address for customer C1?\n",
      "==================================================\n",
      "\n",
      "Initial Response:\n",
      "Stop Reason: tool_use\n",
      "Content: [ContentBlock(text='<thinking>The get_customer_info function retrieves a customer\\'s name, email, and phone number given their customer ID. To call this function, I need the customer_id parameter. The user provided the customer ID \"C1\" in their request, so I have the necessary information to make the API call.</thinking>', type='text'), ContentBlockToolUse(id='toolu_019F9JHokMkJ1dHw5BEh28sA', input={'customer_id': 'C1'}, name='get_customer_info', type='tool_use')]\n",
      "\n",
      "Tool Used: get_customer_info\n",
      "Tool Input:\n",
      "{\n",
      "  \"customer_id\": \"C1\"\n",
      "}\n",
      "\n",
      "Tool Result:\n",
      "{\n",
      "  \"name\": \"John Doe\",\n",
      "  \"email\": \"john@example.com\",\n",
      "  \"phone\": \"123-456-7890\"\n",
      "}\n",
      "\n",
      "Response:\n",
      "Stop Reason: end_turn\n",
      "Content: [ContentBlock(text='The email address for customer C1 (John Doe) is john@example.com.', type='text')]\n",
      "\n",
      "Final Response: The email address for customer C1 (John Doe) is john@example.com.\n",
      "\n",
      "==================================================\n",
      "User Message: What is the status of order O2?\n",
      "==================================================\n",
      "\n",
      "Initial Response:\n",
      "Stop Reason: tool_use\n",
      "Content: [ContentBlock(text='<thinking>\\nBased on the provided functions, the most relevant one for this request is get_order_details, which takes an order_id parameter and returns details about that specific order, including the order status.\\n\\nThe user has provided an order ID in their request - \"O2\". So the required order_id parameter can be filled with this value.\\n\\nSince the required parameter is available, I can proceed with calling the get_order_details function to retrieve the order status for order O2.\\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_01K1u68uC94edXx8MVT35eR3', input={'order_id': 'O2'}, name='get_order_details', type='tool_use')]\n",
      "\n",
      "Tool Used: get_order_details\n",
      "Tool Input:\n",
      "{\n",
      "  \"order_id\": \"O2\"\n",
      "}\n",
      "\n",
      "Tool Result:\n",
      "{\n",
      "  \"id\": \"O2\",\n",
      "  \"product\": \"Gadget B\",\n",
      "  \"quantity\": 1,\n",
      "  \"price\": 49.99,\n",
      "  \"status\": \"Processing\"\n",
      "}\n",
      "\n",
      "Response:\n",
      "Stop Reason: end_turn\n",
      "Content: [ContentBlock(text='Based on the details returned from the get_order_details function, the status of order O2 is \"Processing\".', type='text')]\n",
      "\n",
      "Final Response: Based on the details returned from the get_order_details function, the status of order O2 is \"Processing\".\n",
      "\n",
      "==================================================\n",
      "User Message: Please cancel order O1 for me.\n",
      "==================================================\n",
      "\n",
      "Initial Response:\n",
      "Stop Reason: tool_use\n",
      "Content: [ContentBlock(text='<thinking>\\nThe relevant tool to cancel an order is the cancel_order function. \\nThis function requires an order_id parameter.\\nThe user provided the order ID \"O1\" in their request, so we have the necessary parameter to call the cancel_order function.\\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_01W3ZkP2QCrjHf5bKM6wvT2s', input={'order_id': 'O1'}, name='cancel_order', type='tool_use')]\n",
      "\n",
      "Tool Used: cancel_order\n",
      "Tool Input:\n",
      "{\n",
      "  \"order_id\": \"O1\"\n",
      "}\n",
      "\n",
      "Tool Result:\n",
      "true\n",
      "\n",
      "Response:\n",
      "Stop Reason: end_turn\n",
      "Content: [ContentBlock(text='Based on the confirmation received, your order O1 has been successfully cancelled. Please let me know if there is anything else I can assist you with.', type='text')]\n",
      "\n",
      "Final Response: Based on the confirmation received, your order O1 has been successfully cancelled. Please let me know if there is anything else I can assist you with.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Based on the confirmation received, your order O1 has been successfully cancelled. Please let me know if there is anything else I can assist you with.'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chatbot_interaction(\"Can you tell me the email address for customer C1?\")\n",
    "chatbot_interaction(\"What is the status of order O2?\")\n",
    "chatbot_interaction(\"Please cancel order O1 for me.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And that's it! We've created a customer service chatbot using Claude 3 models and client-side tools. The chatbot can look up customer information, retrieve order details, and cancel orders based on the user's requests. By defining clear tool descriptions and schemas, we enable Claude to effectively understand and utilize the available tools to assist customers.\n",
    "\n",
    "Feel free to expand on this example by integrating with your actual customer database and order management system, and by adding more tools to handle a wider range of customer service tasks."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Anthropic Tools SDK",
   "language": "python",
   "name": "ant-tools-sdk"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
